// Zoop Player by Andrew Davies

"use strict";

function ZoopPlayer( totalBoardPosX, totalBoardPosY, frameIdx )
{
	this.totalBoardPos = new Vec2( totalBoardPosX, totalBoardPosY );
	this.boardDir = "right";
	
	this.colour = g_ZoopColours[ Math.floor( Math.random() * g_ZoopColours.length ) ];
	
	this.state = "normal";
	
	// Normal State
	this.extendInput = false;
	
	// Extend State	
	this.extendSpeed = 6;	
	this.extendStartFrameIdx = 0;
	
	// Contract State
	this.contractStartFrameIdx = 0;	
	this.contractStartLength = 0;	
	
	this.boundingBoxGraphic = new DebugGraphicsRectangle( 0, 0, 0, 0, 0, 0, 0, 1.0 );		
	this.boundingBoxGraphic.hide = true;


	this.sprite = new Sprite( "Sprites/InGame/allMushSprites.png", 1 / 10, frameIdx );
	this.spriteAnims = new Array();	
	this.spriteAnims[ "blue" ] = new Array();		
	this.spriteAnims[ "red" ] = new Array();		
	this.spriteAnims[ "yellow" ] = new Array();	
	this.spriteAnims[ "green" ] = new Array();
	
	var blueDownSpriteAnim = new Array();
	blueDownSpriteAnim.push( new SpriteFrame( 32 * 6,	32 * 0, 32, 32 ) );
	blueDownSpriteAnim.push( new SpriteFrame( 32 * 7,	32 * 0, 32, 32 ) );
	blueDownSpriteAnim.push( new SpriteFrame( 32 * 8,	32 * 0, 32, 32 ) );	
	this.spriteAnims[ "blue" ][ "down" ] = blueDownSpriteAnim;
	
	var blueLeftSpriteAnim = new Array();
	blueLeftSpriteAnim.push( new SpriteFrame( 32 * 6,	32 * 1, 32, 32 ) );
	blueLeftSpriteAnim.push( new SpriteFrame( 32 * 7,	32 * 1, 32, 32 ) );
	blueLeftSpriteAnim.push( new SpriteFrame( 32 * 8,	32 * 1, 32, 32 ) );	
	this.spriteAnims[ "blue" ][ "left" ] = blueLeftSpriteAnim;
	
	var blueRightSpriteAnim = new Array();
	blueRightSpriteAnim.push( new SpriteFrame( 32 * 6,	32 * 2, 32, 32 ) );
	blueRightSpriteAnim.push( new SpriteFrame( 32 * 7,	32 * 2, 32, 32 ) );
	blueRightSpriteAnim.push( new SpriteFrame( 32 * 8,	32 * 2, 32, 32 ) );	
	this.spriteAnims[ "blue" ][ "right" ] = blueRightSpriteAnim;	
	
	var blueUpSpriteAnim = new Array();
	blueUpSpriteAnim.push( new SpriteFrame( 32 * 6,	32 * 3, 32, 32 ) );
	blueUpSpriteAnim.push( new SpriteFrame( 32 * 7,	32 * 3, 32, 32 ) );
	blueUpSpriteAnim.push( new SpriteFrame( 32 * 8,	32 * 3, 32, 32 ) );	
	this.spriteAnims[ "blue" ][ "up" ] = blueUpSpriteAnim;	
	
	var redDownSpriteAnim = new Array();
	redDownSpriteAnim.push( new SpriteFrame( 32 * 9,	32 * 0, 32, 32 ) );
	redDownSpriteAnim.push( new SpriteFrame( 32 * 10,	32 * 0, 32, 32 ) );
	redDownSpriteAnim.push( new SpriteFrame( 32 * 11,	32 * 0, 32, 32 ) );	
	this.spriteAnims[ "red" ][ "down" ] = redDownSpriteAnim;
	
	var redLeftSpriteAnim = new Array();
	redLeftSpriteAnim.push( new SpriteFrame( 32 * 9,	32 * 1, 32, 32 ) );
	redLeftSpriteAnim.push( new SpriteFrame( 32 * 10,	32 * 1, 32, 32 ) );
	redLeftSpriteAnim.push( new SpriteFrame( 32 * 11,	32 * 1, 32, 32 ) );	
	this.spriteAnims[ "red" ][ "left" ] = redLeftSpriteAnim;
	
	var redRightSpriteAnim = new Array();
	redRightSpriteAnim.push( new SpriteFrame( 32 * 9,	32 * 2, 32, 32 ) );
	redRightSpriteAnim.push( new SpriteFrame( 32 * 10,	32 * 2, 32, 32 ) );
	redRightSpriteAnim.push( new SpriteFrame( 32 * 11,	32 * 2, 32, 32 ) );	
	this.spriteAnims[ "red" ][ "right" ] = redRightSpriteAnim;	
	
	var redUpSpriteAnim = new Array();
	redUpSpriteAnim.push( new SpriteFrame( 32 * 9,	32 * 3, 32, 32 ) );
	redUpSpriteAnim.push( new SpriteFrame( 32 * 10,	32 * 3, 32, 32 ) );
	redUpSpriteAnim.push( new SpriteFrame( 32 * 11,	32 * 3, 32, 32 ) );	
	this.spriteAnims[ "red" ][ "up" ] = redUpSpriteAnim;
		
	var yellowDownSpriteAnim = new Array();
	yellowDownSpriteAnim.push( new SpriteFrame( 32 * 0,		32 * 4, 32, 32 ) );
	yellowDownSpriteAnim.push( new SpriteFrame( 32 * 1,		32 * 4, 32, 32 ) );
	yellowDownSpriteAnim.push( new SpriteFrame( 32 * 2,		32 * 4, 32, 32 ) );	
	this.spriteAnims[ "yellow" ][ "down" ] = yellowDownSpriteAnim;
	
	var yellowLeftSpriteAnim = new Array();
	yellowLeftSpriteAnim.push( new SpriteFrame( 32 * 0,		32 * 5, 32, 32 ) );
	yellowLeftSpriteAnim.push( new SpriteFrame( 32 * 1,		32 * 5, 32, 32 ) );
	yellowLeftSpriteAnim.push( new SpriteFrame( 32 * 2,		32 * 5, 32, 32 ) );	
	this.spriteAnims[ "yellow" ][ "left" ] = yellowLeftSpriteAnim;
	
	var yellowRightSpriteAnim = new Array();
	yellowRightSpriteAnim.push( new SpriteFrame( 32 * 0,	32 * 6, 32, 32 ) );
	yellowRightSpriteAnim.push( new SpriteFrame( 32 * 1,	32 * 6, 32, 32 ) );
	yellowRightSpriteAnim.push( new SpriteFrame( 32 * 2,	32 * 6, 32, 32 ) );	
	this.spriteAnims[ "yellow" ][ "right" ] = yellowRightSpriteAnim;	
	
	var yellowUpSpriteAnim = new Array();
	yellowUpSpriteAnim.push( new SpriteFrame( 32 * 0,	32 * 7, 32, 32 ) );
	yellowUpSpriteAnim.push( new SpriteFrame( 32 * 1,	32 * 7, 32, 32 ) );
	yellowUpSpriteAnim.push( new SpriteFrame( 32 * 2,	32 * 7, 32, 32 ) );	
	this.spriteAnims[ "yellow" ][ "up" ] = yellowUpSpriteAnim;	
		
	var greenDownSpriteAnim = new Array();
	greenDownSpriteAnim.push( new SpriteFrame( 32 * 0,		32 * 0, 32, 32 ) );
	greenDownSpriteAnim.push( new SpriteFrame( 32 * 1,		32 * 0, 32, 32 ) );
	greenDownSpriteAnim.push( new SpriteFrame( 32 * 2,		32 * 0, 32, 32 ) );	
	this.spriteAnims[ "green" ][ "down" ] = greenDownSpriteAnim;
	
	var greenLeftSpriteAnim = new Array();
	greenLeftSpriteAnim.push( new SpriteFrame( 32 * 0,		32 * 1, 32, 32 ) );
	greenLeftSpriteAnim.push( new SpriteFrame( 32 * 1,		32 * 1, 32, 32 ) );
	greenLeftSpriteAnim.push( new SpriteFrame( 32 * 2,		32 * 1, 32, 32 ) );	
	this.spriteAnims[ "green" ][ "left" ] = greenLeftSpriteAnim;
	
	var greenRightSpriteAnim = new Array();
	greenRightSpriteAnim.push( new SpriteFrame( 32 * 0,	32 * 2, 32, 32 ) );
	greenRightSpriteAnim.push( new SpriteFrame( 32 * 1,	32 * 2, 32, 32 ) );
	greenRightSpriteAnim.push( new SpriteFrame( 32 * 2,	32 * 2, 32, 32 ) );	
	this.spriteAnims[ "green" ][ "right" ] = greenRightSpriteAnim;	
	
	var greenUpSpriteAnim = new Array();
	greenUpSpriteAnim.push( new SpriteFrame( 32 * 0,	32 * 3, 32, 32 ) );
	greenUpSpriteAnim.push( new SpriteFrame( 32 * 1,	32 * 3, 32, 32 ) );
	greenUpSpriteAnim.push( new SpriteFrame( 32 * 2,	32 * 3, 32, 32 ) );	
	this.spriteAnims[ "green" ][ "up" ] = greenUpSpriteAnim;	
	
	
	this.extendedLength = function( frameIdx )
	{		
		switch( this.state )
		{
		case "extend": return ( frameIdx - this.extendStartFrameIdx ) * this.extendSpeed; break;
		case "contract": return this.contractStartLength - ( ( frameIdx - this.contractStartFrameIdx ) * this.extendSpeed ); break;
		case "normal": return 0; break;
		}
		
		return 0;
	}
		
	this.boundingBox = function( frameIdx, topLeft, bottomRight )
	{
		var extendedLength = this.extendedLength( frameIdx );
		
		topLeft.x = 0;
		topLeft.y = 0;
		bottomRight.x = 0;
		bottomRight.y = 0;
		
		var start = vec2Assign( this.totalBoardPos );
		vec2MulV( start, g_boardUnitSize )
		vec2AddV( start, g_halfBoardUnitSize )
		
		var end = vec2Assign( start );
		
		switch( this.boardDir )
		{
		case "up": 
		{
			end.y -= ( BOARD_UNIT_SIZE_Y / 2 );
			end.y -= extendedLength;			
		}
		break;
		
		case "down": 
		{
			end.y += ( BOARD_UNIT_SIZE_Y / 2 );
			end.y += extendedLength;			
		}
		break;
		
		case "left": 
		{
			end.x -= ( BOARD_UNIT_SIZE_Y / 2 );
			end.x -= extendedLength;			
		}
		break;
		
		case "right": 
		{
			end.x += ( BOARD_UNIT_SIZE_Y / 2 );
			end.x += extendedLength;			
		}
		break;
		
		}	

		var halfWidth = 4;			
		topLeft.x = ( ( start.x < end.x ) ? start.x : end.x ) - halfWidth;
		topLeft.y = ( ( start.y < end.y ) ? start.y : end.y ) - halfWidth;
		bottomRight.x = ( ( start.x > end.x ) ? start.x : end.x ) + halfWidth;
		bottomRight.y = ( ( start.y > end.y ) ? start.y : end.y ) + halfWidth;
	}
	
	this.input = function( input )
	{
		switch( this.state )
		{	
		
		case "extend":
		{
		}
		break;
		
		case "contract":
		{
		}
		break;
		
		case "normal":
		{		
			switch( input )
			{
			
			case 97: // A
			case 37:
			{
				this.totalBoardPos.x--; 
				this.boardDir = "left";
			}
			break; 
			
			case 100: // D
			case 39:
			{
				this.totalBoardPos.x++; 
				this.boardDir = "right";
			}
			break; 	
			
			case 119: // W
			case 38:
			{
				this.totalBoardPos.y--; 
				this.boardDir = "up";
			}
			break;
			
			case 115: // S
			case 40:
			{
				this.totalBoardPos.y++; 
				this.boardDir = "down";
			}
			break; 			
			
			case 32: // Space bar
			{
				this.extendInput = true;
			}
			break;
			
			}
			
			this.totalBoardPos.x = Math.max( this.totalBoardPos.x, ( SUB_BOARD_NUM_UNITS_X * 1 ) );
			this.totalBoardPos.y = Math.max( this.totalBoardPos.y, ( SUB_BOARD_NUM_UNITS_Y * 1 ) );
			this.totalBoardPos.x = Math.min( this.totalBoardPos.x, ( SUB_BOARD_NUM_UNITS_X * 2 ) - 1 );
			this.totalBoardPos.y = Math.min( this.totalBoardPos.y, ( SUB_BOARD_NUM_UNITS_Y * 2 ) - 1 );		
		}
		break;
		
		}
	}
	
	this.update = function( frameIdx, boards )
	{
		var extendedLength = this.extendedLength( frameIdx );				
		this.boundingBoxGraphic.hide = true;
		
		// Update state
		var newState = this.state;
		switch( this.state )
		{	
		
		case "extend":
		{
			var topLeft = new Vec2( 0, 0 );
			var bottomRight = new Vec2( 0, 0 );
			this.boundingBox( frameIdx, topLeft, bottomRight );
					
			this.boundingBoxGraphic.topLeft = vec2Assign( topLeft );
			this.boundingBoxGraphic.bottomRight = vec2Assign( bottomRight );
			this.boundingBoxGraphic.hide = false;
	
			// Iterate over all the baddies in all the boards to see if we've touched any of them
			for( var boardIdx in boards )
			{
				var board = boards[ boardIdx ];
				
				for( var baddyIdx in board.baddies )
				{
					var baddy = board.baddies[ baddyIdx ];					
			
					var baddyTopLeft = new Vec2( 0, 0 );
					var baddyBottomRight = new Vec2( 0, 0 );
					baddy.boundingBox( baddyTopLeft, baddyBottomRight );
					
					if( collisionAABBonAABB( topLeft, bottomRight, baddyTopLeft, baddyBottomRight ) )
					{
						// We've collided with this baddy so if our colours are the same we eat 
						// it and continue to extend, otherwise we swap colours and begin to contract.
						if( baddy.colour == this.colour )
						{
							baddy.kill( frameIdx );
						}
						else
						{
							// Exchange baddy and player colour
							var tempColour = baddy.colour;
							baddy.colour = this.colour;
							this.colour = tempColour;
		
							newState = "contract";
							break;
						}
					}
				}	
			}	

			// Detect collision with the edge of the total board 
			if( collisionAABBonExternalAABB( topLeft, bottomRight, g_boardTopLeft, g_boardBottomRight ) )
			{
				newState = "contract";
				break;
			}
				
		}
		break;
		
		case "contract":
		{
			if( extendedLength <= 0 )
			{
				newState = "normal";
				break;
			}
		}
		break;
		
		case "normal":
		{
			if( this.extendInput )
			{
				newState = "extend";
			}
			this.extendInput = false;
		}
		break;
		
		}
		
		// Transition from current state to new one if needed
		if( this.state != newState )
		{
			// State change needed
			
			// Construct new state
			switch( newState )
			{

			case "extend":
			{
				this.extendStartFrameIdx = frameIdx;
			}
			break;
			
			case "contract":
			{			
				this.contractStartFrameIdx = frameIdx;	
				this.contractStartLength = extendedLength;
			}
			break;
			
			case "normal":
			{
			}
			break;			
			
			}
			
			// Destruct current state
			switch( this.state )
			{

			case "extend":
			{
			}
			break;
			
			case "contract":
			{
			}
			break;
			
			case "normal":
			{
			}
			break;			
			
			}		

			this.state = newState;
		}	
		
		
		this.sprite.update();		
	}
	
	this.draw = function( frameIdx )
	{	
		switch( this.state )
		{
		
		case "extend":
		case "contract":
		{
			var topLeft = new Vec2( 0, 0 );
			var bottomRight = new Vec2( 0, 0 );
			this.boundingBox( frameIdx, topLeft, bottomRight );
			
			var size = new Vec2( 0, 0 );
			vec2rvSubV( size, bottomRight, topLeft );	
			
			context.fillStyle = g_ZoopHexColours[ this.colour ];
			context.fillRect( topLeft.x, topLeft.y, size.x, size.y );
		}
		break;
		
		case "normal":
		{
			var playerX = ( this.totalBoardPos.x * BOARD_UNIT_SIZE_X );
			var playerY = ( this.totalBoardPos.y * BOARD_UNIT_SIZE_Y );
			
			this.sprite.draw( 
				this.spriteAnims[ this.colour ][ this.boardDir ], 
				playerX, playerY,
				BOARD_UNIT_SIZE_X, BOARD_UNIT_SIZE_Y,
				1.0, // alpha
				frameIdx );
		}
		break;
		
		}		
	}	
}
